home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Linux / Kubuntu 8.10 / kubuntu-8.10-desktop-i386.iso / casper / filesystem.squashfs / usr / share / kde4 / apps / guidance-power-manager / guidance-power-manager.py next >
Encoding:
Python Source  |  2008-10-17  |  53.6 KB  |  1,179 lines

  1. #!/usr/bin/python
  2. # -*- coding: utf-8 -*-
  3. """
  4. Copyright 2006-2008 Sebastian K├╝gler, Canonical Ltd, Luka Renko
  5.  
  6. Authors:
  7.     Sebastian K├╝gler <sebas@kde.org>
  8.     Jonathan Riddell <jriddell@ubuntu.com>
  9.     Luka Renko <lure@kubuntu.org>
  10.  
  11. This program is free software; you can redistribute it and/or
  12. modify it under the terms of the GNU General Public License as
  13. published by the Free Software Foundation; either version 2 of
  14. the License, or (at your option) any later version.
  15.  
  16. This program is distributed in the hope that it will be useful,
  17. but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19. GNU General Public License for more details.
  20.  
  21. You should have received a copy of the GNU General Public License
  22. along with this program.  If not, see <http://www.gnu.org/licenses/>.
  23.  
  24. """
  25.  
  26. import sys
  27. import time
  28.  
  29. from PyKDE4.kdecore import KAboutData, KCmdLineArgs, KConfig, i18n, i18nc, i18np, ki18n, ki18nc, KGlobal, KStandardDirs, KLocalizedString
  30. from PyKDE4.kdeui import KUniqueApplication, KApplication,KSystemTrayIcon, UserIcon, KDialog, SmallIcon, KAboutApplicationDialog, KPassivePopup, KMenu, KAction, BarIcon, KShortcut, KXmlGuiWindow, KActionCollection
  31.  
  32. from PyQt4.QtGui import *
  33. from PyQt4.QtCore import *
  34. from PyQt4 import uic
  35.  
  36. from powermanage import *
  37.  
  38. POLL_INTERVAL = 5000 # in milliseconds
  39.  
  40. class PowerManager(QWidget):
  41.     """ Our configuration dialog. """
  42.  
  43.     def __init__(self, parent):
  44.  
  45.         def powerstart(self):
  46.             try:
  47.                 self.powermanager = PowerManage()
  48.             except Exception,e:
  49.                 print "Is Hal running? Failed with error: ", e
  50.                 print "Will try again to connect to HAL in 30 seconds."
  51.                 time.sleep(30)
  52.                 powerstart(self)
  53.  
  54.         QWidget.__init__(self, parent)
  55.  
  56.         #Use local files if in current directory
  57.         if os.path.exists("guidance-power-manager.ui"):
  58.             APPDIR = QDir.currentPath()
  59.         else:
  60.             file =  KStandardDirs.locate("appdata", "guidance-power-manager.ui")
  61.             APPDIR = file.left(file.lastIndexOf("/"))
  62.  
  63.         uic.loadUi(APPDIR + "/" + "guidance-power-manager.ui", self)
  64.  
  65.         # The systray icon should show and hide the KDialogBase, not only this widget,
  66.         # therefore, it gets our parent as parent.
  67.         self.systray = SystemTrayIcon(parent)
  68.         self.icon = "battery-charging"
  69.         self.systray.setIcon(QIcon(BarIcon(self.icon)))
  70.  
  71.         # Configuration file
  72.         app = KApplication.kApplication()
  73.         config = KGlobal.config()
  74.         self.config = config.group("power-manager")
  75.  
  76.         powerstart(self)
  77.  
  78.     def prepare(self):
  79.         """ Prepare UI. """
  80.         self._initBrightness()
  81.         self._initLid()
  82.         self._initBattery()
  83.         self.lastidlesec = 0
  84.  
  85.         self._initConfigKeywords()
  86.  
  87.         self._initUI(self.parent())
  88.  
  89.         self.configToUi()
  90.  
  91.         # Polling: evil.  can't receive signals in python-dbus unless we have a glib mainloop,
  92.         # so we need to poll
  93.         self.pollTimer = QTimer(self)
  94.         self.connect(self.pollTimer, SIGNAL("timeout()"), self.poll)
  95.         self.pollTimer.start(POLL_INTERVAL) # 5 second poll, maybe make this configurable
  96.         self.poll(False)
  97.  
  98.         # check CPU freq policy and notify if it was changed
  99.         msg = self.checkCpuFreq()
  100.         if msg != "":
  101.             self.notify(msg)
  102.  
  103.         self.systray.show()
  104.  
  105.     def _initBrightness(self):
  106.         """ Check for brightness support and disable widgets if it's not there. """
  107.         if not self.powermanager.hasBrightness:
  108.             self.PoweredBrightnessLabel.hide()
  109.             self.PoweredBrightnessSlider.hide()
  110.             self.BatteryBrightnessLabel.hide()
  111.             self.BatteryBrightnessSlider.hide()
  112.  
  113.     def _initLid(self):
  114.         """ Check for lid support and disable widgets if it's not there. """
  115.         if not self.powermanager.hasLid:
  116.             self.LaptopLidRadios.setEnabled(False)
  117.  
  118.     def _initCB(self, combo, options, values):
  119.         """ Initialize QComboBox with proper values from provided options. """
  120.         combo.clear()
  121.         for option in options:
  122.             combo.insertItem(999, values[option])
  123.  
  124.     def _getCB(self, combo, options):
  125.         """ Get current item from QComboBox from config file (string) value. """
  126.         try:
  127.             return options[combo.currentIndex()]
  128.         except IndexError:
  129.             return ""
  130.  
  131.     def _setCB(self, combo, options, default, value):
  132.         """ Set current item in QComboBox from string value. """
  133.         try:
  134.             num = options.index(value)
  135.         except ValueError:
  136.             num = default
  137.             pass
  138.         combo.setCurrentIndex(num)
  139.  
  140.     def _getRB(self, radios, options):
  141.         """ Get current item from QRadioButton from config file (string) value. """
  142.         try:
  143.             for button in self.radioButtonIndex:
  144.                 if button.isChecked():
  145.                     selected = button
  146.             return options[self.radioButtonIndex.index(selected)]
  147.         except IndexError:
  148.             return ""
  149.  
  150.     def _setRB(self, radios, options, default, value):
  151.         """ Set current item in QRadioButton from string value. """
  152.         try:
  153.             num = options.index(value)
  154.         except ValueError:
  155.             num = default
  156.             pass
  157.         button = self.radioButtonIndex[num]
  158.         button.setChecked(True)
  159.  
  160.     def _checkOldConfig(self, value, blank):
  161.         """ Convert old numerical values to keywords. """
  162.         try:
  163.             num_val = int(value)
  164.         except ValueError:
  165.             return value
  166.         if blank:
  167.             if num_val == 0: return 'nothing'
  168.             if num_val == 1: return 'blank'
  169.             if num_val == 2: return 'suspend'
  170.             if num_val == 3: return 'hibernate'
  171.             if num_val == 4: return 'shutdown'
  172.         else:
  173.             if num_val == 0: return 'nothing'
  174.             if num_val == 1: return 'suspend'
  175.             if num_val == 2: return 'hibernate'
  176.             if num_val == 3: return 'shutdown'
  177.         return value
  178.  
  179.     def _initConfigKeywords(self):
  180.         """ Define helper maps used with config file keywords. """
  181.         # map action keyword to displayed name (l10n)
  182.         self.act_name = {}
  183.         self.act_name['nothing'] = i18n("Do nothing")
  184.         self.act_name['blank'] = i18n("Blank screen")
  185.         self.act_name['suspend'] = i18n("Suspend")
  186.         self.act_name['hibernate'] = i18n("Hibernate")
  187.         self.act_name['shutdown'] = i18n("Shutdown")
  188.  
  189.         # map action keyword to action methods
  190.         self.act_call = {}
  191.         self.act_call['nothing'] = None
  192.         self.act_call['blank'] = self.blankScreen
  193.         self.act_call['suspend'] = self.suspend
  194.         self.act_call['hibernate'] = self.hibernate
  195.         self.act_call['shutdown'] = self.shutdown
  196.  
  197.         # map action keyword to action icon used in notification window
  198.         self.act_icon = {}
  199.         self.act_icon['nothing'] = None
  200.         self.act_icon['blank'] = None
  201.         self.act_icon['suspend'] = SmallIcon("system-suspend")
  202.         self.act_icon['hibernate'] = SmallIcon("system-suspend-hibernate")
  203.         self.act_icon['shutdown'] = SmallIcon("system-shutdown")
  204.  
  205.         # map policy keyword to displayed name (l10n)
  206.         self.freq_name = {}
  207.         self.freq_name['dynamic'] = i18nc("CPU policy", "Dynamic")
  208.         self.freq_name['powersave'] = i18nc("CPU policy", "Powersave")
  209.         self.freq_name['performance'] = i18nc("CPU policy", "Performance")
  210.  
  211.         # map policy keyword to policy change methods
  212.         self.freq_call = {}
  213.         self.freq_call['dynamic'] = self.setCpuPolicyDynamic
  214.         self.freq_call['powersave'] = self.setCpuPolicyPowersave
  215.         self.freq_call['performance'] = self.setCpuPolicyPerformance
  216.  
  217.     def _initUI(self, parent):
  218.         """ Build dynamic parts of the UI: context menu and tooltip. """
  219.         disableSuspend = self.config.readEntry("disableSuspend", QVariant(False)).toBool()
  220.         disableHibernate = self.config.readEntry("disableHibernate", QVariant(False)).toBool()
  221.         self.canSuspend = self.powermanager.canSuspend and not disableSuspend
  222.         self.canHibernate = self.powermanager.canHibernate and not disableHibernate
  223.  
  224.         # Connect some signals.  Updates in the dialogue apply instantly
  225.         self.connect(self.PoweredBrightnessSlider, SIGNAL("valueChanged(int)"), self.changePoweredBrightness)
  226.         self.connect(self.BatteryBrightnessSlider, SIGNAL("valueChanged(int)"), self.changeBatteryBrightness)
  227.  
  228.         self.tooltip = QFrame()
  229.         self.tooltip.setFrameStyle(QFrame.Box | QFrame.Plain)
  230.         #set widget to use tooltip colours
  231.         palette = self.tooltip.palette()
  232.         palette.setColor(QPalette.Window, palette.color(QPalette.ToolTipBase))
  233.         palette.setColor(QPalette.WindowText, palette.color(QPalette.ToolTipText))
  234.         self.tooltip.setLayout(QVBoxLayout())
  235.         self.systray.setToolTip(self.tooltip)
  236.  
  237.         self._addBatteryWidgets()
  238.  
  239.         self._addCpuWidgets()
  240.  
  241.         # fill actions for LID
  242.         self.lid_act = ['nothing', 'blank', 'suspend', 'hibernate', 'shutdown']
  243.         self.lid_act_def = 0
  244.         # hide LID close actions that are not supported
  245.         if not self.canSuspend:
  246.             self.laptopClosedSuspend.hide()
  247.         if not self.canHibernate:
  248.             self.laptopClosedHibernate.hide()
  249.  
  250.         # fill in only CPU policies that are supported by HW
  251.         self.cb_freq = []       # list of supported cpu freq policies
  252.         self.cb_freq_def = 0    # always use first policy as default
  253.         if self.powermanager.hasCpuFreqGovernors:
  254.             self.cb_freq = self.powermanager.getSupportedCpuPolicies()
  255.         if len(self.cb_freq) > 0:
  256.             self._initCB(self.PoweredFreqCombo, self.cb_freq, self.freq_name)
  257.             self._initCB(self.BatteryFreqCombo, self.cb_freq, self.freq_name)
  258.         else:
  259.             self.PoweredFreqLabel.hide()
  260.             self.PoweredFreqCombo.hide()
  261.             self.BatteryFreqLabel.hide()
  262.             self.BatteryFreqCombo.hide()
  263.  
  264.         # fill actions in Idle/Critical battery combo boxes
  265.         self.cb_act = ['nothing']       # list of supported actions (keywords)
  266.         self.cb_act_def_critical = 0    # default action when critical battery
  267.         if self.canSuspend:
  268.             self.cb_act.append('suspend')
  269.         if self.canHibernate:
  270.             self.cb_act.append('hibernate')
  271.             self.cb_act_def_critical = len(self.cb_act) - 1 # hibernate
  272.         self.cb_act.append('shutdown')
  273.         if self.cb_act_def_critical == 0:
  274.             self.cb_act_def_critical = len(self.cb_act) - 1  # shutdown
  275.         self._initCB(self.PoweredIdleCombo, self.cb_act, self.act_name)
  276.         self._initCB(self.BatteryIdleCombo, self.cb_act, self.act_name)
  277.         self._initCB(self.BatteryCriticalCombo, self.cb_act, self.act_name)
  278.  
  279.         self.connect(self.PoweredIdleCombo,SIGNAL("activated(int)"),self.slotPoweredIdleActivated)
  280.         self.connect(self.BatteryIdleCombo,SIGNAL("activated(int)"),self.slotBatteryIdleActivated)
  281.         self.connect(self.BatteryCriticalCombo,SIGNAL("activated(int)"),self.slotBatteryCriticalActivated)
  282.  
  283.         # add suspend/hibernate to tray's context menu
  284.         menu = self.systray.contextMenu()
  285.         if self.canSuspend:
  286.             suspendAction = self.systray.actionCollection().addAction("suspend")
  287.             suspendAction.setText(i18n("Suspend"))
  288.             suspendAction.setIcon(QIcon(self.act_icon['suspend']))
  289.             self.connect(suspendAction, SIGNAL("triggered()"), self.suspend)
  290.             menu.addAction(suspendAction)
  291.         if self.canHibernate:
  292.             hibernateAction = self.systray.actionCollection().addAction("hibernate")
  293.             hibernateAction.setText(i18n("Hibernate"))
  294.             hibernateAction.setIcon(QIcon(self.act_icon['hibernate']))
  295.             self.connect(hibernateAction, SIGNAL("triggered()"), self.hibernate)
  296.             menu.addAction(hibernateAction)
  297.  
  298.         # In KDE 4 it seems we can't attach to X keysyms, only Qt keys.
  299.         # For no good reason whatsoever Qt turns XF86Launch4 into Qt::Key_Launch6, see qt4-x11-4.4.1/gui/kernel/qkeymapper_x11.cpp
  300.         # and does not map XF86LaunchE or XF86Sleep etc.
  301.         # In Kubuntu we map keys using a custom xmodmap file from the kubuntu-default-settings package which is loaded on starting X, 
  302.         # other distros will need to do something similar.
  303.         brightnessUpAction = self.systray.actionCollection().addAction("brightness_up")
  304.         brightnessUpAction.setText("Brightness Up")
  305.         brightnessUpAction.setShortcut(KShortcut(Qt.Key_Launch6))
  306.         brightnessUpAction.setGlobalShortcut(KShortcut(Qt.Key_Launch6))
  307.         self.connect(brightnessUpAction, SIGNAL("triggered(bool)"), self.setBrightnessUp)
  308.  
  309.         brightnessUpAction = self.systray.actionCollection().addAction("brightness_down")
  310.         brightnessUpAction.setText("Brightness Down")
  311.         brightnessUpAction.setShortcut(KShortcut(Qt.Key_Launch5))
  312.         brightnessUpAction.setGlobalShortcut(KShortcut(Qt.Key_Launch5))
  313.         self.connect(brightnessUpAction, SIGNAL("triggered(bool)"), self.setBrightnessDown)
  314.  
  315.         standbyAction = self.systray.actionCollection().addAction("standby")
  316.         standbyAction.setText("Standby")
  317.         standbyAction.setShortcut(KShortcut(Qt.Key_Standby))
  318.         standbyAction.setGlobalShortcut(KShortcut(Qt.Key_Standby))
  319.         self.connect(standbyAction, SIGNAL("triggered(bool)"), self.suspend)
  320.  
  321.         # add list of cpu frequency governors
  322.         if self.powermanager.hasCpuFreqGovernors and len(self.cb_freq) > 0:
  323.             submenu = KMenu(menu)
  324.             actionGroup = QActionGroup(self)
  325.             actionGroup.setExclusive(True)
  326.             currentPolicy = self.powermanager.getCpuPolicy()
  327.             self.policyActions = {}
  328.             for policy in self.cb_freq:
  329.                 action = KAction(self.freq_name[policy], actionGroup)
  330.                 action.setCheckable(True)
  331.                 self.policyActions[policy] = action
  332.                 self.connect(action, SIGNAL("triggered()"), self.freq_call[policy])
  333.                 submenu.addAction(action)
  334.                 if policy == currentPolicy:
  335.                     action.setChecked(True)
  336.  
  337.             submenu.setTitle(i18n("CPU policy"))
  338.             menu.addMenu(submenu)
  339.  
  340.         # KGlobalAccel crashes the application in pykde
  341.         # see http://mats.gmd.de/pipermail/pykde/2006-May/013224.html
  342.         #self.globalActions = KGlobalAccel(self)
  343.         #self.suspendShortcut = KShortcut("XF86Sleep")
  344.         #self.hibernateShortcut = KShortcut("XF86Standby")
  345.         #self.hshutdownShortcut = KShortcut("XF86PowerOff")
  346.         #self.globalActions.insert("suspend", i18n("Suspend"), i18n("what's this?"), self.suspendShortcut, #self.suspendShortcut, self.suspend)
  347.         #self.globalActions.updateConnections()
  348.  
  349.         self.radioButtonIndex = [self.laptopClosedNone, self.laptopClosedBlank, self.laptopClosedSuspend, self.laptopClosedHibernate, self.laptopClosedShutdown]
  350.  
  351.     def setBrightness(self):
  352.         print "setbrightness"
  353.  
  354.     def _initBattery(self):
  355.         """ Remove non-battery-related widgets if there's no battery bay. """
  356.         if not self.powermanager.hasBattery:
  357.             # Disable the Batterybox in the config dialogue,
  358.             self.BatteryBox.setEnabled(False)
  359.             # And change the icon in the systray, remove the restore option
  360.             # This way, we're basically becoming a systray applet, you can
  361.             # hibernate and suspend from
  362.             self.systray.setIcon(QIcon(BarIcon(self.icon)))
  363.         if self.powermanager.hasAC:
  364.             self.wasOnBattery = self.powermanager.onBattery()
  365.  
  366.     def configToUi(self):
  367.         """ Setup the the values from the config file in the UI."""
  368.         # brightness.
  369.         if self.powermanager.hasBrightness:
  370.             brightness_high = self.powermanager.brightness_levels
  371.             self.BatteryBrightnessSlider.setMaximum(self.powermanager.brightness_levels-1)
  372.             self.PoweredBrightnessSlider.setMaximum(self.powermanager.brightness_levels-1)
  373.             batteryBrightness = self.config.readEntry("batteryBrightness", QVariant(int(brightness_high/2)))
  374.             batteryBrightness = batteryBrightness.toInt()
  375.             batteryBrightness = batteryBrightness[0]
  376.             poweredBrightness = self.config.readEntry("poweredBrightness", QVariant(brightness_high))
  377.             poweredBrightness = poweredBrightness.toInt()
  378.             poweredBrightness = poweredBrightness[0]
  379.             self.BatteryBrightnessSlider.setValue(batteryBrightness) #default middle
  380.             self.PoweredBrightnessSlider.setValue(poweredBrightness) #default highest
  381.  
  382.             tt_text = "Every step increases or decreases the brightness by %i%%" % int(100/brightness_high)
  383.             self.BatteryBrightnessSlider.setToolTip(tt_text)
  384.             self.PoweredBrightnessSlider.setToolTip(tt_text)
  385.  
  386.         lockOnResume = self.config.readEntry("lockOnResume", QVariant(True))
  387.         lockOnResume = lockOnResume.toBool()
  388.         self.lockScreenOnResume.setChecked(lockOnResume)
  389.  
  390.         # Idletime-related configuration
  391.         self._setCB(self.PoweredIdleCombo, self.cb_act, 0, str(self.config.readEntry("poweredIdleAction")))
  392.         poweredIdleTime = self.config.readEntry("poweredIdleTime", QVariant(60))
  393.         poweredIdleTime = poweredIdleTime.toInt()
  394.         poweredIdleTime = poweredIdleTime[0]
  395.         self.PoweredIdleTime.setValue(poweredIdleTime)
  396.         self._setCB(self.BatteryIdleCombo, self.cb_act, 0, str(self.config.readEntry("batteryIdleAction")))
  397.         batteryIdleTime = self.config.readEntry("batteryIdleTime", QVariant(10))
  398.         batteryIdleTime = batteryIdleTime.toInt()
  399.         batteryIdleTime = batteryIdleTime[0]
  400.         self.BatteryIdleTime.setValue(batteryIdleTime)
  401.  
  402.         self._setCB(self.PoweredFreqCombo, self.cb_freq, self.cb_freq_def, str(self.config.readEntry("poweredFreqPolicy")))
  403.         self._setCB(self.BatteryFreqCombo, self.cb_freq, self.cb_freq_def, str(self.config.readEntry("batteryFreqPolicy")))
  404.  
  405.         batteryIdleTime = self.config.readEntry("batteryIdleTime", QVariant(10))
  406.         batteryIdleTime = batteryIdleTime.toInt()
  407.         batteryIdleTime = batteryIdleTime[0]
  408.         self.BatteryIdleTime.setValue(batteryIdleTime) # default Do nothing
  409.         # battery critical and lid actions.
  410.         self._setCB(self.BatteryCriticalCombo, self.cb_act, self.cb_act_def_critical, self._checkOldConfig(self.config.readEntry("batteryCriticalAction", ""), False))
  411.         self._setRB(self.LaptopLidRadios, self.lid_act, self.lid_act_def, self._checkOldConfig(self.config.readEntry("laptopLidAction", ""), True))
  412.         criticalRemainTime = self.config.readEntry("criticalRemainTime", QVariant(BATTERY_CRITICAL_MINUTES))
  413.         criticalRemainTime = criticalRemainTime.toInt()
  414.         criticalRemainTime = criticalRemainTime[0]
  415.         self.CriticalRemainTime.setValue(criticalRemainTime)
  416.         self.criticalLevel = self.CriticalRemainTime.value()
  417.  
  418.         # Call some slots to disable various spinboxes if necessary
  419.         self.slotBatteryCriticalActivated()
  420.         self.slotPoweredIdleActivated()
  421.         self.slotBatteryIdleActivated()
  422.  
  423.     def uiToConfig(self):
  424.         """ Read all values from the UI and write them to the config file. """
  425.         self.config.writeEntry("poweredBrightness", QVariant(self.PoweredBrightnessSlider.value()))
  426.         self.config.writeEntry("batteryBrightness", QVariant(self.BatteryBrightnessSlider.value()))
  427.  
  428.         self.config.writeEntry("poweredIdleTime", QVariant(self.PoweredIdleTime.value()))
  429.         self.config.writeEntry("poweredIdleAction", QVariant(self._getCB(self.PoweredIdleCombo, self.cb_act)))
  430.         self.config.writeEntry("batteryIdleTime", QVariant(self.BatteryIdleTime.value()))
  431.         self.config.writeEntry("batteryIdleAction", QVariant(self._getCB(self.BatteryIdleCombo, self.cb_act)))
  432.         self.config.writeEntry("poweredFreqPolicy", QVariant(self._getCB(self.PoweredFreqCombo, self.cb_freq)))
  433.         self.config.writeEntry("batteryFreqPolicy", QVariant(self._getCB(self.BatteryFreqCombo, self.cb_freq)))
  434.  
  435.         self.config.writeEntry("batteryCriticalAction", QVariant(self._getCB(self.BatteryCriticalCombo, self.cb_act)))
  436.         self.config.writeEntry("criticalRemainTime", QVariant(self.CriticalRemainTime.value()))
  437.  
  438.         self.config.writeEntry("laptopLidAction", QVariant(self._getRB(self.LaptopLidRadios, self.lid_act)))
  439.         self.config.writeEntry("lockOnResume", QVariant(self.lockScreenOnResume.isChecked()))
  440.  
  441.         self.criticalLevel = self.CriticalRemainTime.value()
  442.  
  443.         self.config.sync()
  444.  
  445.     def showBrightnessPopup(self):
  446.         if self.powermanager.onBattery():
  447.             value=self.BatteryBrightnessSlider.value()*100/self.BatteryBrightnessSlider.maximum()
  448.         else:
  449.             value=self.PoweredBrightnessSlider.value()*100/self.PoweredBrightnessSlider.maximum()
  450.         self.brightnessPopup = KPassivePopup.message('<b>Brightness:</b> '+str(value)+'%', self.systray)
  451.         """pop.setTimeout(3000)"""
  452.         self.brightnessPopup.show()
  453.  
  454.     def setBrightnessUp(self):
  455.         """Increments slider value by 5%"""
  456.         if self.powermanager.onBattery():
  457.             self.BatteryBrightnessSlider.setValue(float(self.BatteryBrightnessSlider.value())+max(float(self.BatteryBrightnessSlider.maximum())/float(10),1))
  458.         else:
  459.             self.PoweredBrightnessSlider.setValue(float(self.PoweredBrightnessSlider.value())+max(float(self.PoweredBrightnessSlider.maximum())/float(10),1))
  460.         self.showBrightnessPopup()
  461.  
  462.     def setBrightnessDown(self):
  463.         """Decrements slider value by 5%"""
  464.         if self.powermanager.onBattery():
  465.             self.BatteryBrightnessSlider.setValue(float(self.BatteryBrightnessSlider.value())-max(float(self.BatteryBrightnessSlider.maximum())/float(10),1))
  466.         else:
  467.             self.PoweredBrightnessSlider.setValue(float(self.PoweredBrightnessSlider.value())-max(float(self.PoweredBrightnessSlider.maximum())/float(10),1))
  468.         self.showBrightnessPopup()
  469.  
  470.     #def getBrightness(self):
  471.     #  """Work with percentages - it's a bit nicer"""
  472.     #  if self.powermanager.onBattery():
  473.     #    value=self.BatteryBrightnessSlider.value()*100/self.BatteryBrightnessSlider.maxValue()
  474.     #  else:
  475.     #    value=self.PoweredBrightnessSlider.value()*100/self.PoweredBrightnessSlider.maxValue()
  476.     #  return QString(str(value))
  477.  
  478.     def lockScreen(self):
  479.         """ locks the screen using dbus """
  480.         # init dbus session bus
  481.         bus = dbus.SessionBus()
  482.         # assign screensaver object
  483.         dbus_screensaver = bus.get_object('org.freedesktop.ScreenSaver',
  484.         '/ScreenSaver')
  485.         # make screensaver methods available: Lock(), GetActive(), SetActive(bool),
  486.         ScreenSaver = dbus.Interface(dbus_screensaver, 'org.freedesktop.ScreenSaver')
  487.         # Lock the Screen or print a warning.
  488.         # No return value when successful, not sure otherwise.
  489.         try:
  490.             ScreenSaver.Lock()
  491.         except:
  492.             print "Unable to lock the screen. There is a problem with the dbus connection to org.freedesktop.ScreenSaver.Lock()"
  493.  
  494.     def suspend(self):
  495.         """ Lock the screen and initiate a suspend to RAM (S3). """
  496.         if self.config.readEntry("lockOnResume", QVariant(True)).toBool():
  497.             self.lockScreen()
  498.         try:
  499.             self.warningPopup.hide()
  500.         except AttributeError:
  501.             pass # No warningpopup, that's OK.
  502.         self.powermanager.suspend()
  503.         self.powermanager.resetIdleSeconds()
  504.  
  505.     def hibernate(self):
  506.         """ Lock the screen and initiate a suspend to disk (S4). """
  507.         if self.config.readEntry("lockOnResume", QVariant(True)).toBool():
  508.             self.lockScreen()
  509.         try:
  510.             self.warningPopup.hide()
  511.         except AttributeError:
  512.             pass # No warningpopup, that's OK.
  513.         self.powermanager.hibernate()
  514.         self.powermanager.resetIdleSeconds()
  515.  
  516.     def shutdown(self):
  517.         """ Perform system shutdown. """
  518.         self.powermanager.shutdown()
  519.  
  520.     def _policyChangeMessage(self, policy):
  521.         """ Properly localized text notification for policy change. """
  522.         if policy == "dynamic":
  523.             return i18n("CPU frequency policy changed to dynamic.")
  524.         elif policy == "performance":
  525.             return i18n("CPU frequency policy changed to performance.")
  526.         elif policy == "powersave":
  527.             return i18n("CPU frequency policy changed to powersave.")
  528.         else:
  529.             return i18n("CPU frequency policy changed to %1.", policy)
  530.  
  531.     def setCpuPolicyDynamic(self):
  532.         """Change frequ for all cpu"""
  533.         self.powermanager.setCpuPolicy('dynamic')
  534.         self.notify(self._policyChangeMessage('dynamic'))
  535.  
  536.     def setCpuPolicyPerformance(self):
  537.         """Change frequ for all cpu"""
  538.         self.powermanager.setCpuPolicy('performance')
  539.         self.notify(self._policyChangeMessage('performance'))
  540.  
  541.     def setCpuPolicyPowersave(self):
  542.         """Change frequ for all cpu"""
  543.         self.powermanager.setCpuPolicy('powersave')
  544.         self.notify(self._policyChangeMessage('powersave'))
  545.         self.blankScreen()
  546.  
  547.     #for if/when we add a DBus interface
  548.     def trySuspend(self):
  549.         """ If supported, lock the screen and initiate a suspend to RAM (S3). """
  550.         if self.canSuspend:
  551.            self.suspend()
  552.         else:
  553.            print "Warning: DBUS suspend() called, but not supported."
  554.  
  555.     def tryHibernate(self):
  556.         """ If supported, lock the screen and initiate a suspend to disk (S4). """
  557.         if self.canHibernate:
  558.            self.hibernate()
  559.         else:
  560.            print "Warning: DBUS hibernate() called, but not supported."
  561.  
  562.     def blankScreen(self):
  563.         """ Lock and blank screen. """
  564.         if self.config.readEntry("lockOnResume", QVariant(True)).toBool():
  565.             self.lockScreen()
  566.         self.powermanager.blankScreen()
  567.  
  568.     def _getIcon(self):
  569.         """ Set systray icon depending on battery status/level. """
  570.         if self.powermanager.hasBattery:
  571.             if self.batt_state == "not present":
  572.                 self.icon = "battery-missing"
  573.             if self.batt_state == "charged":
  574.                 self.icon = "battery-charging"
  575.             elif self.batt_state == "discharging":
  576.                 if self.batt_level >= 95:
  577.                     self.icon = "battery-100"
  578.                 elif self.batt_level < 95 and self.batt_level >= 85:
  579.                     self.icon = "battery-080"
  580.                 elif self.batt_level < 85 and self.batt_level >= 75:
  581.                     self.icon = "battery-080"
  582.                 elif self.batt_level < 75 and self.batt_level >= 60:
  583.                     self.icon = "battery-060"
  584.                 elif self.batt_level < 65 and self.batt_level >= 45:
  585.                     self.icon = "battery-060"
  586.                 elif self.batt_level < 45 and self.batt_level >= 30:
  587.                     self.icon = "battery-040"
  588.                 elif self.batt_level < 30 and self.batt_level >= 20:
  589.                     self.icon = "battery-040"
  590.                 elif self.batt_level < 20 and self.batt_level >= 10:
  591.                     self.icon = "battery-caution"
  592.                 elif self.batt_level < 10 and self.batt_level >= 5:
  593.                     self.icon = "battery-low"
  594.                 else:
  595.                     self.icon = "battery-low"
  596.             elif self.batt_state == "charging":
  597.                 if self.batt_level >= 95:
  598.                     self.icon = "battery-charging"
  599.                 elif self.batt_level < 95 and self.batt_level >= 85:
  600.                     self.icon = "battery-charging-080"
  601.                 elif self.batt_level < 85 and self.batt_level >= 75:
  602.                     self.icon = "battery-charging-080"
  603.                 elif self.batt_level < 75 and self.batt_level >= 60:
  604.                     self.icon = "battery-charging-060"
  605.                 elif self.batt_level < 65 and self.batt_level >= 45:
  606.                     self.icon = "battery-charging-060"
  607.                 elif self.batt_level < 45 and self.batt_level >= 30:
  608.                     self.icon = "battery-charging-040"
  609.                 elif self.batt_level < 30 and self.batt_level >= 20:
  610.                     self.icon = "battery-charging-040"
  611.                 elif self.batt_level < 20 and self.batt_level >= 10:
  612.                     self.icon = "battery-charging-caution"
  613.                 elif self.batt_level < 10 and self.batt_level >= 5:
  614.                     self.icon = "battery-charging-low"
  615.                 else:
  616.                     self.icon = "battery-charging-low"
  617.         else:
  618.             self.icon = "battery-missing"
  619.         return self.icon
  620.  
  621.     def getIcon(self):
  622.         """ Return current icon."""
  623.         return BarIcon(self.icon)
  624.  
  625.     def setIcon(self):
  626.         """ Change the systray/tooltip icon."""
  627.         oldIcon = self.icon
  628.         self.icon = self._getIcon()
  629.         if self.icon != oldIcon:
  630.             icon = BarIcon(self.icon)
  631.             self.systray.setIcon(QIcon(icon))
  632.             self.BattPixmap.setPixmap(icon)
  633.             self.parent().setWindowIcon(QIcon(icon))
  634.             menu = self.systray.contextMenu() #hmm, doesn't work?
  635.             menu.setIcon(QIcon(icon))
  636.  
  637.     def notify(self, msg, icon=None):
  638.         """ Send a notification popup. """
  639.         if icon:
  640.             icon = QPixmap(icon)
  641.         else:
  642.             icon = QPixmap(SmallIcon("dialog-information"))
  643.         try:
  644.             del self.warningPopup
  645.         except:
  646.             pass
  647.         KPassivePopup.message("Power Manager", msg, icon, self.systray)
  648.  
  649.     def poll(self,notify=True):
  650.         """ Check for changes in plugged in status, battery status and laptop lid closed status. """
  651.         debug( "------------ POLL ---------------")
  652.  
  653.         try:
  654.             self.powermanager.checkHAL()
  655.             # Battery stuff:
  656.             # check for last state, and run plugged / unplugged message if the state changed.
  657.             if self.powermanager.hasBattery:
  658.                 plugged_num = 0
  659.                 self.batt_state = "not present" # unknown yet
  660.                 self.batt_level = self.batt_remain = 0
  661.                 self.batt_rate = self.batt_charge = self.batt_full = 0
  662.                 for batt in self.powermanager.batteries:
  663.                     state, level, remain, rate, current, full = self.powermanager.getBatteryState(batt)
  664.                     self._updateBatteryWidget(batt, state, level, remain, rate)
  665.  
  666.                     # notify plugged/unplugged batteries
  667.                     if state == "not present":
  668.                         if self.powermanager.batteryIsPresent[batt]:
  669.                             print "been removed"
  670.                             self.notify(i18n("The battery has been removed."))
  671.                             self.powermanager.batteryIsPresent[batt] = False
  672.                     else: # battery present
  673.                         if not self.powermanager.batteryIsPresent[batt]:
  674.                             print "inserted"
  675.                             self.notify(i18n("The battery has been inserted."))
  676.                             self.powermanager.batteryIsPresent[batt] = True
  677.  
  678.                         # get cumulative charge levels/rate
  679.                         self.batt_rate += rate
  680.                         self.batt_charge += current
  681.                         self.batt_full += full
  682.  
  683.                         # calculate overall level (average of present batteries)
  684.                         self.batt_remain += remain
  685.                         self.batt_level += level
  686.                         plugged_num += 1
  687.  
  688.                         # calculate overall state (charging/discharging/charged)
  689.                         if state in ("charging","discharging"):
  690.                             self.batt_state = state
  691.                         elif not self.batt_state in ("charging, discharging"):
  692.                             self.batt_state = state
  693.  
  694.                 # if we know charge and full -> recalculate overall level
  695.                 if self.batt_full > 0 and self.batt_charge > 0:
  696.                     self.batt_level = 100 * self.batt_charge / self.batt_full
  697.                 else:
  698.                     # if more than one battery present, we need to calculate average level
  699.                     if plugged_num > 1:
  700.                         self.batt_level /= plugged_num
  701.  
  702.                 # if rate is reported, calculate remaining time on our own
  703.                 if self.batt_rate > 0:
  704.                     if self.batt_state == "charging":
  705.                         self.batt_remain = 3600 * (float(self.batt_full - self.batt_charge) / self.batt_rate)
  706.                     if self.batt_state == "discharging":
  707.                         self.batt_remain = 3600 * (float(self.batt_charge) / self.batt_rate)
  708.  
  709.                 remain_h = self.batt_remain/3600
  710.                 remain_m = (self.batt_remain/60)%60
  711.  
  712.                 blabel = i18n("<b>Battery:</b>")
  713.                 if self.batt_state == "charged":
  714.                     blabel += i18n(" fully charged")
  715.                 elif self.batt_state == "charging":
  716.                     blabel += ki18nc("hours:minutes", " %1:%2h to charge").subs(remain_h).subs(remain_m, 2).toString()
  717.                 elif self.batt_state == "discharging":
  718.                     blabel += ki18nc("hours:minutes", " %1:%2h remaining").subs(remain_h).subs(remain_m, 2).toString()
  719.                 self.BattMainLabel.setText(blabel)
  720.  
  721.                 # update tray icon if needed
  722.                 self.setIcon()
  723.  
  724.                 # check battery state
  725.                 self.checkBatteryCritical()
  726.  
  727.                 # check Idletime
  728.                 self.checkIdletime()
  729.  
  730.             # CPU stuff
  731.             self._updateCpuWidgets()
  732.  
  733.             if self.powermanager.hasBattery:
  734.                 on_battery = self.powermanager.onBattery()
  735.                 if self.powermanager.wasOnBattery != on_battery:
  736.                     self.powermanager.wasOnBattery = on_battery
  737.                     debug("poll: states differ")
  738.                     if not on_battery:
  739.                         debug("poll: Now on AC")
  740.                         if notify:
  741.                             self.powerHasBeenPlugged()
  742.                     else:
  743.                         debug("poll: Now on battery")
  744.                         if notify:
  745.                             self.powerHasBeenUnplugged()
  746.                 else:
  747.                     debug("poll: state is the same")
  748.  
  749.             # Lid stuff
  750.             if self.powermanager.hasLid:
  751.                 if self.powermanager.getLidClosedState():
  752.                     if not self.powermanager.lidClosedState:
  753.                         self.powermanager.lidClosedState = True
  754.  
  755.                         action = self._getRB(self.LaptopLidRadios, self.lid_act)
  756.                         if not self.act_name.has_key(action):
  757.                             action = self.act_name[self.lid_act_def]
  758.  
  759.                         if self.act_call[action] != None:
  760.                             if action == "nothing":
  761.                                 note = i18n("Laptop lid is closed, hibernating now.")
  762.                             elif action == "blank":
  763.                                 note = i18n("Laptop lid is closed, blanking screen now.")
  764.                             elif action == "suspend":
  765.                                 note = i18n("Laptop lid is closed, suspending now.")
  766.                             elif action == "hibernate":
  767.                                 note = i18n("Laptop lid is closed, hibernating now.")
  768.                             elif action == "shutdown":
  769.                                 note = i18n("Laptop lid is closed, shutting down now.")
  770.                             self.notify(note, self.act_icon[action])
  771.                             QTimer.singleShot(2000, self.act_call[action])
  772.                 else:
  773.                     self.powermanager.lidClosedState = False
  774.         except Exception,e:
  775.                 print "Is Hal running? Failed with error: ", e
  776.                 print "Will try again on the next polling attempt."
  777.  
  778.     def _addBatteryWidgets(self):
  779.         """ Adds progressbars to show battery status to the tooltip."""
  780.         BattLayout = QHBoxLayout(None)
  781.  
  782.         self.BattPixmap = QLabel(self.tooltip)
  783.         self.BattPixmap.setSizePolicy(QSizePolicy(QSizePolicy.Fixed,QSizePolicy.Fixed))
  784.         self.BattPixmap.setPixmap(BarIcon(self.icon))
  785.         self.BattPixmap.setScaledContents(1)
  786.         BattLayout.addWidget(self.BattPixmap)
  787.         self.BattMainLabel = QLabel(self.tooltip)
  788.         self.BattMainLabel.setText(i18n("<b>Battery:</b>"))
  789.         BattLayout.addWidget(self.BattMainLabel)
  790.  
  791.         # Add to tooltip
  792.         self.tooltip.layout().addLayout(BattLayout)
  793.  
  794.         # Create a progressbar and a label for every battery found, and add it to tooltip
  795.         self.BattLabel = {}
  796.         self.BattLayout = {}
  797.         self.BattProgress = {}
  798.         i = 1
  799.         for batt in self.powermanager.batteries:
  800.             self.BattLayout[batt] = QHBoxLayout(None)
  801.             self.BattLabel[batt] = QLabel(self.tooltip)
  802.             if len(self.powermanager.batteries) > 1:
  803.                 self.BattLabel[batt].setText(i18n("Battery %i" % i))
  804.             self.BattLayout[batt].addWidget(self.BattLabel[batt])
  805.             self.BattProgress[batt] = QProgressBar(self.tooltip)
  806.             self.BattProgress[batt].setMinimumSize(QSize(200,0))
  807.             self.BattLayout[batt].addWidget(self.BattProgress[batt])
  808.             self.tooltip.layout().addLayout(self.BattLayout[batt])
  809.             i += 1
  810.  
  811.     def _updateBatteryWidget(self, batt, state, level, remain, rate):
  812.         """ Retrieve battery information and update the related widgets accordingly. """
  813.         self.BattProgress[batt].setEnabled(True)
  814.         self.BattProgress[batt].setMaximum(100)
  815.         self.BattProgress[batt].setValue(level)
  816.         if state == "not present":
  817.             self.BattProgress[batt].setFormat(i18n("not present"))
  818.         elif state == "charging":
  819.             self.BattProgress[batt].setFormat(i18n("Charging (%p%)"))
  820.         elif state == "discharging":
  821.             if rate > 0:
  822.                 showrate = rate/1000
  823.                 self.BattProgress[batt].setFormat(ki18nc("%1 is discharge rate in Watts", "Discharging (%p%) - %1 W").subs(showrate).toString())
  824.             else:
  825.                 self.BattProgress[batt].setFormat(i18n("Discharging (%p%)"))
  826.         else:
  827.             self.BattProgress[batt].setFormat(i18n("%p%"))
  828.  
  829.     def _addCpuWidgets(self):
  830.         """ Adds progressbars to show CPU frequencies to the tooltip."""
  831.         if not SHOW_CPUFREQ:
  832.             return
  833.         if len(self.powermanager.cpus) == 0:
  834.             return
  835.  
  836.         LabelLayout = QHBoxLayout(None)
  837.  
  838.         self.CpuPixmap = QLabel(self.tooltip)
  839.         self.CpuPixmap.setSizePolicy(QSizePolicy(QSizePolicy.Fixed,QSizePolicy.Fixed))
  840.         self.CpuPixmap.setPixmap(BarIcon("cpu"))
  841.         self.CpuPixmap.setScaledContents(1)
  842.         LabelLayout.addWidget(self.CpuPixmap)
  843.         self.CpuMainLabel = QLabel(self.tooltip)
  844.         self.CpuMainLabel.setText(i18n("<b>CPU Frequency:</b>"))
  845.         LabelLayout.addWidget(self.CpuMainLabel)
  846.  
  847.         # Add to tooltip
  848.         self.tooltip.layout().addLayout(LabelLayout)
  849.  
  850.         # Create a progressbar and a label for every CPU found, and add it to tooltip
  851.         self.CpuLabel = {}
  852.         self.CpuLayout = {}
  853.         self.CpuProgress = {}
  854.         i = 1
  855.         for cpu in self.powermanager.cpus:
  856.             self.CpuLayout[cpu] = QHBoxLayout(None)
  857.             self.CpuLabel[cpu] = QLabel(self.tooltip)
  858.             if len(self.powermanager.cpus) > 1:
  859.                 self.CpuLabel[cpu].setText(i18n("Processor %1", i))
  860.             self.CpuLayout[cpu].addWidget(self.CpuLabel[cpu])
  861.             self.CpuProgress[cpu] = QProgressBar(self.tooltip)
  862.             self.CpuProgress[cpu].setFormat("%v MHz")
  863.             self.CpuLayout[cpu].addWidget(self.CpuProgress[cpu])
  864.             self.tooltip.layout().addLayout(self.CpuLayout[cpu])
  865.             i += 1
  866.  
  867.     def slotPoweredIdleActivated(self, index=False):
  868.         """ Signal slot for activated powered idle action. """
  869.         if not index:
  870.             index = self.PoweredIdleCombo.currentIndex()
  871.         self.PoweredIdleTime.setEnabled(index != 0)
  872.  
  873.     def slotBatteryIdleActivated(self, index=False):
  874.         """ Signal slot for activated battery idle action. """
  875.         if not index:
  876.             index = self.BatteryIdleCombo.currentIndex()
  877.         self.BatteryIdleTime.setEnabled(index != 0)
  878.  
  879.     def slotBatteryCriticalActivated(self, index=False):
  880.         """ Signal slot for activated battery critical action. """
  881.         if not index:
  882.             index = self.BatteryCriticalCombo.currentIndex()
  883.         self.CriticalRemainTime.setEnabled(index != 0)
  884.  
  885.     def _updateCpuWidgets(self):
  886.         """ Retrieve CPU freq information and update the related widgets accordingly. """
  887.         if not SHOW_CPUFREQ:
  888.             return
  889.         if len(self.powermanager.cpus) == 0:
  890.             return
  891.  
  892.         policy = self.powermanager.getCpuPolicy()
  893.         text = ""
  894.         if self.freq_name.has_key(policy):
  895.             policyString = unicode(self.freq_name[policy])
  896.             text = i18nc("%1 is one of the CPU policies", "<b>CPU Frequency:</b> %1", policyString)
  897.         else:
  898.             text = i18nc("%1 is one of the CPU policies", "<b>CPU Frequency:</b> %1", policy)
  899.         self.CpuMainLabel.setText(text)
  900.  
  901.         for cpu in self.powermanager.cpus:
  902.             cpustate = self.powermanager.getCpuState(cpu)
  903.             if not cpustate['online']:
  904.                 self.CpuProgress[cpu].setEnabled(False)
  905.             else:
  906.                 self.CpuProgress[cpu].setEnabled(True)
  907.                 self.CpuProgress[cpu].setMaximum(cpustate['max'])
  908.                 self.CpuProgress[cpu].setValue(cpustate['cur'])
  909.         if policy != "" or policy and self.cb_freq:
  910.             self.policyActions[policy].setChecked(True)
  911.  
  912.     def changePoweredBrightness(self, level=None):
  913.         """ Mains-powered brigthness slider has been moved. """
  914.         # Check if the state applies and adjust brightness immediately.
  915.         if not self.powermanager.onBattery() and self.powermanager.hasBrightness:
  916.             if not level:
  917.                 level = self.PoweredBrightnessSlider.value()
  918.             self.powermanager.adjustBrightness(level)
  919.  
  920.     def changeBatteryBrightness(self, level=None):
  921.         """ Battery-powered brigthness slider has been moved. """
  922.         # Check if the state applies and adjust brightness immediately.
  923.         if self.powermanager.onBattery() and self.powermanager.hasBrightness:
  924.             if not level:
  925.                 level = self.BatteryBrightnessSlider.value()
  926.             self.powermanager.adjustBrightness(level)
  927.  
  928.     def checkCpuFreq(self):
  929.         """ Adjust CPU frequency policy according to current state """
  930.         if not self.powermanager.hasCpuFreqGovernors:
  931.             return ""
  932.  
  933.         if self.powermanager.onBattery():
  934.             policy = str(self.config.readEntry("batteryFreqPolicy"))
  935.         else:
  936.             policy = str(self.config.readEntry("poweredFreqPolicy"))
  937.         if policy == "":
  938.            policy = 'dynamic'
  939.  
  940.         # check if specified policy is supported by HW
  941.         if not policy in self.cb_freq:
  942.             print "Warning: policy from config file not supported: ", policy
  943.             return ""
  944.  
  945.         current_policy = self.powermanager.getCpuPolicy()
  946.         if current_policy != policy:
  947.             debug("Switching CPU policy from %s to %s." % (current_policy, policy))
  948.             self.powermanager.setCpuPolicy(policy)
  949.             return self._policyChangeMessage(policy)
  950.         elif current_policy == 'dynamic':
  951.             debug("Dynamic policy -> update policy (conservative/ondemand)")
  952.             self.powermanager.setCpuPolicy(policy)
  953.  
  954.         debug("CPU policy will stay %s" % current_policy)
  955.         return ""
  956.  
  957.     def powerHasBeenUnplugged(self):
  958.         """ Actions to perform when the plug has been pulled."""
  959.         if self.powermanager.hasBrightness:
  960.             self.powermanager.adjustBrightness(self.BatteryBrightnessSlider.value())
  961.         self.powermanager.setPowerSave(True)
  962.         self.checkBatteryCritical()
  963.         self.changeBatteryBrightness()
  964.         self.powermanager.setScreensaverBlankOnly(True)
  965.         self.powermanager.resetIdleSeconds()
  966.         msg = self.checkCpuFreq()
  967.         if self.powermanager.hasAC:
  968.             self.notify(i18n("The AC adapter has been unplugged, switching to battery mode.")+"\n"+msg, self.getIcon())
  969.  
  970.     def powerHasBeenPlugged(self):
  971.         """ Actions to perform when AC adapter has been plugged in. """
  972.         if self.powermanager.hasBrightness:
  973.             self.powermanager.adjustBrightness(self.PoweredBrightnessSlider.value())
  974.         self.powermanager.setPowerSave(False)
  975.         self.changePoweredBrightness()
  976.         self.powermanager.setScreensaverBlankOnly(False)
  977.         msg = self.checkCpuFreq()
  978.         self.powermanager.resetIdleSeconds()
  979.         self.notify(i18n("The AC adapter has been plugged in, switching to AC mode.")+"\n"+msg, self.getIcon())
  980.  
  981.     def checkBatteryCritical(self):
  982.         """ Check for warning and critical battery label and notify-warn or
  983.             initiate the configured action. """
  984.  
  985.         if not self.powermanager.hasBattery:
  986.             return
  987.  
  988.         if self.batt_state == "discharging":
  989.             currentLevel = int(self.batt_remain/60)
  990.  
  991.             warningLevel = self.criticalLevel + 5 # warn five minutes before critical
  992.             criticalLevel = self.criticalLevel
  993.  
  994.             debug("CurrentBat: %i, WarningBat: %i, CriticalBat: %i" % (currentLevel, warningLevel, criticalLevel))
  995.             # We only want to suspend if the chargelevel is above a certain threshold,
  996.             # it sometimes takes some time for HAL to report remaining time correctly
  997.             if currentLevel <= criticalLevel and self.batt_level < CHARGE_LEVEL_THRESHOLD:
  998.                 if not self.powermanager.criticalBatteryState and self.powermanager.onBattery():
  999.                     self.powermanager.criticalBatteryState = True
  1000.  
  1001.                     action = str(self.config.readEntry("batteryCriticalAction"))
  1002.                     if not self.act_name.has_key(action):
  1003.                         action = self.cb_act[self.cb_act_def_critical]
  1004.  
  1005.                     if action == "nothing":
  1006.                         note = i18n("You are about to run out of battery power, doing nothing now.")
  1007.                     elif action == "blank":
  1008.                         note = i18n("You are about to run out of battery power, blanking screen now.")
  1009.                     elif action == "suspend":
  1010.                         note = i18n("You are about to run out of battery power, suspending now.")
  1011.                     elif action == "hibernate":
  1012.                         note = i18n("You are about to run out of battery power, hibernating now.")
  1013.                     elif action == "shutdown":
  1014.                         note = i18n("You are about to run out of battery power, shutting down now.")
  1015.                     self.notify(note, self.act_icon[action])
  1016.                     if self.act_call[action] != None:
  1017.                         QTimer.singleShot(2000, self.act_call[action])
  1018.             else:
  1019.                 self.powermanager.criticalBatteryState = False
  1020.                 if currentLevel <= warningLevel and self.batt_level < CHARGE_LEVEL_THRESHOLD:
  1021.                     if not self.powermanager.warningBatteryState:
  1022.                         self.powermanager.warningBatteryState = True
  1023.                         self.notify(i18n("You are low on battery power."), self.getIcon())
  1024.                 else:
  1025.                     self.powermanager.warningBatteryState = False
  1026.  
  1027.     def checkIdletime(self):
  1028.         """ Reads the idle time and does some action. """
  1029.         idlesec = round(self.powermanager.getIdleSeconds()/60, 2)
  1030.  
  1031.         disableSuspend = self.config.readEntry("disableSuspend", QVariant(False)).toBool()
  1032.         disableHibernate = self.config.readEntry("disableHibernate", QVariant(False)).toBool()
  1033.  
  1034.         if self.powermanager.onBattery():
  1035.             idleTime = self.config.readEntry("batteryIdleTime", QVariant(10)).toInt()
  1036.             action = str(self.config.readEntry("batteryIdleAction", QString("")))
  1037.         else:
  1038.             idleTime = self.config.readEntry("poweredIdleTime", QVariant(60)).toInt()
  1039.             action = str(self.config.readEntry("poweredIdleAction", QString("")))
  1040.         if not self.act_name.has_key(action):
  1041.             action = 'nothing'
  1042.  
  1043.         if idlesec - self.lastidlesec > 100:
  1044.             debug("last: %u" % (idlesec - self.lastidlesec))
  1045.             return # probably bogus idleseconds right after suspend
  1046.         self.lastidlesec = idlesec
  1047.         if self.act_call[action] == None:
  1048.             return # doing nothing anyway
  1049.         if idlesec > idleTime:
  1050.             if action == "nothing":
  1051.                 note = i18np("System idle for at least %1 minute, doing nothing now.", "System idle for at least %1 minutes, doing nothing now.", idleTime)
  1052.             elif action == "blank":
  1053.                 note = i18np("System idle for at least %1 minute, blanking screen now.", "System idle for at least %1 minutes, blanking screen now.", idleTime)
  1054.             elif action == "suspend":
  1055.                 note = i18np("System idle for at least %1 minute, suspending now.", "System idle for at least %1 minutes, suspending now.", idleTime)
  1056.             elif action == "hibernate":
  1057.                 note = i18np("System idle for at least %1 minute, hibernating now.", "System idle for at least %1 minutes, hibernating now.", idleTime)
  1058.             elif action == "shutdown":
  1059.                 note = i18np("System idle for at least %1 minute, shutting down now.", "System idle for at least %1 minutes, shutting down now.", idleTime)
  1060.             self.notify(note, self.act_icon[action])
  1061.             QTimer.singleShot(2000, self.act_call[action])
  1062.  
  1063. class PowermanagerApp(KDialog):
  1064.     """ The KDialog providing the OK, Apply and Cancel buttons."""
  1065.  
  1066.     def __init__(self,parent=None):
  1067.         """ Initialise dialog and set mainwidget. """
  1068.         KDialog.__init__(self, parent)
  1069.         self.setButtons(KDialog.ButtonCode(KDialog.Ok | KDialog.Cancel | KDialog.Apply | KDialog.User1))
  1070.         self.pmwidget = PowerManager(self)
  1071.         self.setButtonText(KDialog.User1, i18n("About"))
  1072.  
  1073.         if not self.pmwidget.powermanager.isLaptop():
  1074.             print "This is not a laptop, quitting ... "
  1075.             sys.exit(1)
  1076.  
  1077.         self.pmwidget.prepare()
  1078.  
  1079.         self.setMainWidget(self.pmwidget)
  1080.         self.resize(0, 0)
  1081.  
  1082.         self.connect(self, SIGNAL("okClicked()"), self.slotOk)
  1083.         self.connect(self, SIGNAL("applyClicked()"), self.slotApply)
  1084.         self.connect(self, SIGNAL("cancelClicked()"), self.slotCancel)
  1085.         self.connect(self, SIGNAL("user1Clicked()"), self.slotUser1)
  1086.         self.aboutus = KAboutApplicationDialog(aboutData, self)
  1087.         self.setWindowTitle(i18n("Guidance Power Manager")) #KDialog doesn't use app name for some reason
  1088.  
  1089.     def slotOk(self):
  1090.         """ The OK button has been pressed, save configuration and pass on do whatever
  1091.             needs to be done by KDialog. """
  1092.         self.pmwidget.uiToConfig()
  1093.         self.pmwidget.checkCpuFreq()
  1094.  
  1095.     def slotApply(self):
  1096.         """ The Apply button has been pressed, save configuration and pass on do whatever
  1097.             needs to be done by KDialog. """
  1098.         self.pmwidget.uiToConfig()
  1099.         self.pmwidget.checkCpuFreq()
  1100.  
  1101.     def slotCancel(self):
  1102.         """ The Cancel button has been pressed, reset some values and hide dialogue. """
  1103.         # In case brightness has changed, we reset it to the configured value.
  1104.         if self.pmwidget.powermanager.hasBrightness:
  1105.             brightness_high = self.pmwidget.powermanager.brightness_levels
  1106.             if not self.pmwidget.powermanager.onBattery():
  1107.                 poweredBrightness = self.pmwidget.config.readEntry("poweredBrightness", QVariant(brightness_high))
  1108.                 level = poweredBrightness.toInt()
  1109.                 level = level[0]
  1110.             else:
  1111.                 batteryBrightness = self.pmwidget.config.readEntry("batteryBrightness", QVariant(int(brightness_high/2)))
  1112.                 level = batteryBrightness.toInt()
  1113.                 level = level[0]
  1114.             self.pmwidget.powermanager.adjustBrightness(level)
  1115.         self.pmwidget.configToUi()
  1116.  
  1117.     def slotUser1(self):
  1118.         self.aboutus.show()
  1119.  
  1120. class SystemTrayIcon(KSystemTrayIcon):
  1121.     """This class needed because we can't use a widget for a tooltip in Qt 4 (only text)
  1122.        Also we can't use a KPassivePopup because KSystemTrayIcon is not a QWidget """
  1123.  
  1124.     def setToolTip(self, toolTip):
  1125.         """ set the toolTip widget """
  1126.         self.toolTip = toolTip
  1127.         self.toolTip.setWindowFlags(Qt.ToolTip)
  1128.  
  1129.     def event(self, event):
  1130.         """ overloaded to pick up tooltip events and show our widget
  1131.             would be nice to hide it when the mouse leaves but systemtrayicons
  1132.             don't get that event so use a timer """
  1133.         if event.type() == QEvent.ToolTip:
  1134.             self.toolTip.show()
  1135.             x = self.geometry().x() - self.toolTip.width()
  1136.             y = self.geometry().y() - self.toolTip.height()
  1137.             if x < 0:
  1138.                 x += self.geometry().width() + self.toolTip.width()
  1139.             if y < 0:
  1140.                 y += self.geometry().height() + self.toolTip.height()
  1141.             self.toolTip.move(x, y)
  1142.             QTimer.singleShot(3000, self.hideToolTip)
  1143.             return True
  1144.         else:
  1145.             return KSystemTrayIcon.event(self, event)
  1146.  
  1147.     def hideToolTip(self):
  1148.         self.toolTip.hide()
  1149.  
  1150. # the old "not destroying KApplication last"
  1151. # make a real main(), and make app global. app will then be the last thing deleted (C++)
  1152. def main():
  1153.     mainWindow = PowermanagerApp(None)
  1154.     #mainWindow.show()
  1155.     app.setQuitOnLastWindowClosed(False) #else Qt 4 likes to quit when we close or hide the dialogue
  1156.     app.exec_()
  1157.  
  1158. #--------------- main ------------------
  1159. if __name__ == '__main__':
  1160.  
  1161.     appName     = "guidance-power-manager"
  1162.     catalog     = ""
  1163.     programName = ki18n("Guidance Power Manager")
  1164.     version     = "4.1.1"
  1165.     description = ki18n("Applet for battery info and setting brightness")
  1166.     license     = KAboutData.License_GPL
  1167.     copyright   = ki18n("Copyright 2006-2008 Sebastian K├╝gler, Canonical Ltd, Luka Renko")
  1168.     text        = KLocalizedString()
  1169.     homePage    = "https://launchpad.net/guidance"
  1170.     bugEmail    = ""
  1171.  
  1172.     aboutData   = KAboutData(appName, catalog, programName, version, description,
  1173.                                 license, copyright, text, homePage, bugEmail)
  1174.  
  1175.     KCmdLineArgs.init(sys.argv, aboutData)
  1176.  
  1177.     app = KUniqueApplication()
  1178.     main()
  1179.